package cn.edu.hit.kg;

import cn.edu.hit.core.Document;
import cn.edu.hit.core.conf.ConfigureLoader;
import org.neo4j.driver.v1.*;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * @author Wang 2016年12月12日
 * neo驱动
 */

public class NeoDriver implements AutoCloseable {
    String mUrl;
    static Map<String,Driver> driver = new ConcurrentHashMap<>();

//    static {
//        ConfigureLoader loader = ConfigureLoader.getInstance();
//        Document conf = loader.getBaseConfigure();
//        url = conf.getString("NEO4J_BOLT", "bolt://localhost");
//        username = conf.getString("USERNAME", "neo4j");
//        password = conf.getString("PASSWORD", "123456");
//    }

//    public NeoDriver() {
//        this(url,username,password);
//    }

    public NeoDriver(String url,String username,String password){
        if (!driver.containsKey(url)){
            driver.put(url,GraphDatabase.driver(
                    url,
                    AuthTokens.basic(username, password),
                    Config.build().withEncryptionLevel(Config.EncryptionLevel.NONE).toConfig()));
        }
        mUrl = url;
    }

    //原因：每个session只能用于一个线程内，将session放在此处是为了可以并行化
    public StatementResult query(String cyper) {
        return execute(session -> session.run(cyper));
    }

    public StatementResult query(String cyper, Map<String, Object> params) {
        return execute(session -> session.run(cyper, params));
    }

    public StatementResult query(String cyper, Value value) {
        return execute(session -> session.run(cyper, value));
    }

    public <R> R execute(Function<Session, R> sessionRFunction) {
        try (Session session = driver.get(mUrl).session()) {
            return sessionRFunction.apply(session);
        }
    }

    public void executeVoid(Consumer<Session> sessionConsumer) {
        try (Session session = driver.get(mUrl).session()) {
            sessionConsumer.accept(session);
        }
    }

    public void close() {
        Driver d = driver.remove(mUrl);
        if (d!=null){
            d.close();
        }
    }
}
